Skip to content

Comments

Fix Ruby 3.3+ ARM64 segfault during shutdown#19

Open
phillip-haydon wants to merge 24 commits intomainfrom
ph/ruby-3.3-arm64-compatibility-01-01-2026
Open

Fix Ruby 3.3+ ARM64 segfault during shutdown#19
phillip-haydon wants to merge 24 commits intomainfrom
ph/ruby-3.3-arm64-compatibility-01-01-2026

Conversation

@phillip-haydon
Copy link

Summary

Fixes segfault on Ruby 3.3+ ARM64 (Apple Silicon) during shutdown/finalization.

Problem

Ruby 3.3+ introduced the M:N thread scheduler where M Ruby threads are managed by N native threads. On ARM64, rb_current_execution_context() uses TLS (Thread Local Storage) via __tls_get_addr(), which can segfault when TLS blocks are freed during Ruby shutdown.

Solution

Inspired by Datadog dd-trace-rb, this PR:

  1. Replaces unsafe TLS access with a safe pattern using rb_thread_current() (public API) + RTYPEDDATA_TYPE + rb_check_typeddata() for type-safe thread struct extraction
  2. Adds version guards (RG_RUBY_VER_GE(3, 3)) to conditionally use the safe path on Ruby 3.3+
  3. Updates dependencies for Ruby 3.3/3.4 compatibility

Changes

  • ext/raygun/raygun_tracer.c: Added rb_rg_thread_struct_from_object() with lazy-initialized type descriptor cache
  • ext/raygun/raygun_tracer.h: Updated rb_rg_get_current_thread_trace_context() macro for Ruby 3.3+
  • ext/raygun/raygun_coercion.h: Added RG_RUBY_VER_GE() version comparison macro
  • ext/raygun/extconf.rb: Improved error messages for missing headers
  • raygun-apm.gemspec: Updated debase-ruby_core_source dependency and Ruby version range
  • Gemfile: Added gems removed from Ruby 3.4+ defaults (mutex_m, ostruct, csv)

Testing

Ruby Version Status
3.1.6 ✅ Pass (100 runs, no segfaults)
3.3.7 ✅ Pass (100 runs, no segfaults)
3.4.2 ✅ Pass (100 runs, no segfaults)

Oracle Review

The changes were reviewed by the Oracle which confirmed:

  • Core fix is correct and follows established patterns
  • Lazy initialization is safe and idempotent
  • Backward compatibility is maintained
  • Residual risks are modest and relate to future Ruby internals changes

- Add safe thread struct extraction using rb_thread_current() instead of
  rb_current_execution_context() which crashes on ARM64 due to TLS issues
- Add version guards for Ruby 3.3+ M:N thread scheduler compatibility
- Update debase-ruby_core_source dependency to support Ruby 3.3/3.4
- Add missing gems for Ruby 3.4+ (mutex_m, ostruct, csv)
- Cache rb_rg_id_group for performance optimization

Tested on Ruby 3.1.6, 3.3.7, and 3.4.2 without segfaults.
Address PR feedback - the < 5.0 constraints were overly aggressive
since Ruby 4.0 was just released. Removed version ceiling to allow
future Ruby versions to work without modification.
phillip-haydon and others added 22 commits January 8, 2026 08:25
…ee, bump to 1.1.15.pre2

- Fix old-style C function definitions () -> (void) across all source files
- Fix use-after-free false positive in rax.c with temp variable pattern
- Add -Wno-use-after-free to extconf.rb for remaining third-party rax patterns
- Bump version to 1.1.15.pre2
- Update gem:native:darwin rbconfig paths for Ruby 3.0.7, 3.1.7, 3.2.9
- Replace Kernel#open with File.open
- Add README.md documenting all 7 platform gems, build steps, release process
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants